package main
// 事物的操作步骤  开始事务、提交事务、回滚事务
import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql-master"  //init()
)
// 声明结构体
type user struct{
	id int
	name string
	age int
}

// 定义全局变量数据库连接池db
var db *sql.DB  //是一个连接池
func initDB()(err error){
	// 数据库的信息
	dsn:="root:123@tcp(127.0.0.1:3306)/sql_test"
	// 连接数据库
	db,err =sql.Open("mysql",dsn)  //不会校验用户名和密码是否正确.  sql.Opne("数据库类型",数据库信息)
	if err!=nil{                   //dsn格式不正确的时候会报错
		return
	}
	err=db.Ping()  //这才是真正尝试连接数据库
	if err!=nil{
		return
	}
	// 设置数据库连接池的最大连接数
	db.SetMaxOpenConns(100)
	// 设置最大空闲连接数
	db.SetMaxIdleConns(10)
	return
}
// 数据库事物示例
func transactionDemo(){
	// 1.开启事务
	tx,err:=db.Begin()
	if err!=nil{
			fmt.Printf("begin failed,err:%v\n",err)
			return
		}
	// 2.执行多个sql语句
	sqlStr:=`update user set age=age+2 where id =1;`
	sqlStr1:=`update xxx set age=age-2 where id =4;`
	// 执行sqlStr
	_,err=tx.Exec(sqlStr)
	if err!=nil{
		// 要回滚
		tx.Rollback()
		fmt.Println("提交sqlStr出错了,要回滚!!")
		return
	}
	// 执行sqlStr1
	_,err=tx.Exec(sqlStr1)
	if err!=nil{
		// 要回滚
		tx.Rollback()
		fmt.Println("提交sqlStr1出错了,要回滚!!")
		return
	}
	// 上面两部sql执行成功，就提交本次事务
	err=tx.Commit()
	if err!=nil{
		// 要回滚
		tx.Rollback()
		fmt.Println("提交事务出错了,要回滚!!")
		return
	}
	fmt.Println("事务执行成功!!")
}

func main(){
	err:=initDB()
	if err!=nil {
		fmt.Printf("init db failed,err:%v\n",err)
	}
	transactionDemo()
}